# -*- coding: utf-8 -*-..,
##############################################################################
#
#    @author: PhongND
#    Copyright (C) 2014 Crea8s (http://www.crea8s.com) All Rights Reserved.
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################


# -*- coding: UTF-8 -*-
'''
    magento

    :copyright: (c) 2014-2015 by PhongND
    :license: AGPLv3, see LICENSE for more details
'''
import magento
from openerp.osv import fields, osv
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp


class Sale(osv.Model):
    """Sale
    """
    _inherit = 'sale.order'

    _columns = dict(
        crea8s_magento_id=fields.integer('Magento ID', readonly=True),
        crea8s_magento_instance=fields.many2one(
            'crea8s.magento.instance', 'Magento Instance', readonly=True,
        ),
        crea8s_magento_store_view=fields.many2one(
            'crea8s.magento.store', 'Store', readonly=True,
        ),
        crea8s_magento_view=fields.many2one(
            'crea8s.magento.view', 'View', readonly=True,
        ),
    )
    
    _sql_constraints = [(
        'magento_id_instance_unique', 'unique(crea8s_magento_id, crea8s_magento_instance)',
        'A sale must be unique in an instance' # PhongND
    )]
    
    
    def crea8s_find_or_create_using_magento_data(
        self, cursor, user, data_importing, context
    ):
        """
        Find or Create sale using magento data

        :param cursor: Database cursor
        :param user: ID of current user
        :param data_importing: Order Data from magento
        :param context: Application context
        :returns: Browse record of sale order found/created
        """
        sale = self.crea8s_find_using_magento_data(
            cursor, user, data_importing, context
        )
        
        if not sale:
#             return False
            sale = self.crea8s_create_using_magento_data(
                cursor, user, data_importing, context
            )
        else:
            sale = self.crea8s_create_using_magento_data(
                cursor, user, data_importing, context, updateID = sale.id
            )

        return sale

    def crea8s_find_using_magento_data(
        self, cursor, user, data_importing, context
    ):
        """
        Create sale using magento data
         
        :param cursor: Database cursor
        :param user: ID of current user
        :param data_importing: Order Data from magento
        :param context: Application context
        :returns: Browse record of sale order found
        """
        # each sale has to be unique in an instance of magento
        sale_ids = self.search(cursor, user, [
            ('crea8s_magento_id', '=', int(data_importing['order_id'])),
            ('crea8s_magento_instance', '=', context.get('magento_instance')),
        ], context=context)

        return sale_ids and self.browse(
            cursor, user, sale_ids[0], context
        ) or None

    def crea8s_create_using_magento_data(self, cursor, user, data_importing, context, updateID=None):
        """
        Create a sale order from magento data
 
        :param cursor: Database cursor
        :param user: ID of current user
        :param data_importing: Order Data from magento
        :param context: Application context
        :param context: Application context
        :param updateID: sale.id
        :returns: Browse record of sale order created
        """
        ormCurrency = self.pool.get('res.currency')
        ormStore = self.pool.get('crea8s.magento.store')
        ormView = self.pool.get('crea8s.magento.view')
        ormPartner = self.pool.get('res.partner')
        ormSOline = self.pool.get('sale.order.line')
 
#         objStore = ormStore.browse(
#             cursor, user, context['magento_store'], context
#         )
        objView = ormView.browse(
            cursor, user, context['magento_view'], context
        )
        if not objView.store.shop:
            raise osv.except_osv(
                _('Not Found!'),
                _(
                    'Magento Store \'%s\' should have a shop configured.'
                    % objView.store.name
                )
            )
        if not objView.store.shop.pricelist_id:
            raise osv.except_osv(
                _('Not Found!'),
                _(
                    'Shop on store \'%s\' does not have a pricelist!'
                    % objView.store.name
                )
            )
 
        instance = objView.instance
        currencyid = None
        currencyids = []
        currencyids = ormCurrency.search(
            cursor, user, [('name', 'ilike', data_importing['order_currency_code'])], context=context
        ) # == ormCurrency.search_using_magento_code(
        if len(currencyids) > 0:
            currencyid = currencyids[0]
        
        if data_importing['customer_id']:
            print '+sale.py > crea8s_create...: ormPartner.crea8s_find_or_create_using_magento_id.....'
            partner = ormPartner.crea8s_find_or_create_using_magento_id(
                cursor, user, data_importing['customer_id'], context
            )
        else:
            print '+sale.py > crea8s_create...: ormPartner.crea8s_create_using_magento_data.....'
            partner = ormPartner.crea8s_create_using_magento_data(
                cursor, user, {
                    'firstname': data_importing['customer_firstname'],
                    'lastname': data_importing['customer_lastname'],
                    'email': data_importing['customer_email'],
                    'telephone': data_importing.get('telephone') or None,
#                     'magento_id': 0, # customer_id?? 
    #             'customer_id': 0,
# #                     'address': {},
                },
                context
            )
 
#         partner_invoice_address = \
#             ormPartner.crea8s_find_or_create_address_as_partner_using_magento_data(
#                 cursor, user, data_importing['billing_address'], partner, context
#             )
# 
#         partner_shipping_address = \
#             ormPartner.crea8s_find_or_create_address_as_partner_using_magento_data(
#                 cursor, user, data_importing['shipping_address'], partner, context
#             )
 
        sale_data = {
            'name': str(instance.order_prefix) + data_importing['increment_id'] + '_c01', # increment_id  
            'shop_id': objView.store.shop.id,
            'date_order': data_importing['created_at'].split()[0],
            'partner_id': partner.id,
            'pricelist_id': objView.store.shop.pricelist_id.id,
            'currency_id': currencyid, #currency.id,
            'partner_invoice_id': 6, #partner_invoice_address.id,
            'partner_shipping_id': 6, #partner_shipping_address.id,
            'crea8s_magento_id': int(data_importing['order_id']),
            'crea8s_magento_instance': instance.id,
            'crea8s_magento_view': objView.id,
#             'order_line': [],
            'order_line': self.crea8s_get_item_line_data_using_magento_data(
                cursor, user, data_importing, context
            )
        }
 
        if float(data_importing.get('shipping_amount')):
            print 'sale.py: shipping_amount.....'
            sale_data['order_line'].append(
                self.crea8s_get_shipping_line_data_using_magento_data(
                    cursor, user, data_importing, context
                )
            )
#  
        if float(data_importing.get('discount_amount')):
            print 'sale.py: discount_amount.....'
            sale_data['order_line'].append(
                self.crea8s_get_discount_line_data_using_magento_data(
                    cursor, user, data_importing, context
                )
            )
 
 
        
        sale_id = None
        if updateID:
            # remove SO lines
            arrSOline_ids = ormSOline.search(cursor, user, [('id', '=', updateID)], context=None) # not search: order_id
#             ormSOline.unlink(cursor, user, arrSOline_ids, context=None) # maybe error: Cannot delete a sales order line which is in state 'confirmed'.")
            
            # update SO
            sale_id = self.write(cursor, user, [updateID], sale_data, context=context)
            sale_id = updateID
        else:
            sale_id = self.create(
                cursor, user, sale_data, context=context
            )
        
#         # Process sale nowx
#         self.process_sale_using_magento_state(
#             cursor, user, sale, data_importing['state'], context
#         )
#         
        sale = self.browse(cursor, user, sale_id, context)
        return sale
    
    
    #?? discont...
    def crea8s_get_discount_line_data_using_magento_data(self, cursor, user, data_importing, context):
        """
        Create a discount line for the given sale using magento data

        :param cursor: Database cursor
        :param user: ID of current user
        :param data_importing: Order Data from magento 
        :param context: Application context
        """
    
        ormWebsite = self.pool.get('crea8s.magento.website')
        return (0, 0, {
            'name': 'Magento Discount', # ....data_importing['discount_description'] or
            'price_unit': float(data_importing.get('discount_amount', 0.00)),
            'product_uom':
                ormWebsite.get_default_uom(
                    cursor, user, context
            ).id,
            'magento_notes': data_importing.get('discount_description'),
        }) # (0, 0, {})
    
    
    #?? shipping
    def crea8s_get_shipping_line_data_using_magento_data(self, cursor, user, data_importing, context):

        print 'sale.py: crea8s_get_shipping_line_data_using_magento_data'
        ormWebsite = self.pool.get('crea8s.magento.website')
        ormProduct = self.pool.get('product.product')
        
        taxes = self.crea8s_get_magento_shipping_tax(
            cursor, user, data_importing, context
        )
        
#         line_data = []
        values = {
            'name': 'Magento Shipping',
            'price_unit': float(data_importing.get('shipping_amount', 0.00)), #nono: shipping_incl_tax
            'product_uom': ormWebsite.get_default_uom(
                    cursor, user, context
            ).id,  # context: magento_website ???
#             'product_uom_qty': float(item['qty_ordered']),
            'magento_notes': ' - '.join([
                data_importing['shipping_method'],
                data_importing['shipping_description']
            ]),
            'type': 'make_to_order',
            'tax_id': [(6, 0, taxes)], #???
            
        }

        line_data = (0, 0, values) # ??, 0, 0, values   # okok
        
        print '+ line_data: ' + str(line_data)
        return line_data
        
        
    
    def crea8s_get_item_line_data_using_magento_data(self, cursor, user, data_importing, context):
        """
        Create a sale order from magento data
 
        :param cursor: Database cursor
        :param user: ID of current user
        :param data_importing: Order Data from magento
        :param context: Application context
        :returns: Browse record of sale order created
        """
        
        ormWebsite = self.pool.get('crea8s.magento.website')
        ormProduct = self.pool.get('product.product')
        ormMRP_Bom = self.pool.get('mrp.bom') #???

        line_data = []
        for item in data_importing['items']:
            if not item['parent_item_id']: #??

                taxes = self.crea8s_get_magento_taxes(cursor, user, item, context)
                # If its a top level product, create it
                values = {
                    'name': item['name'],
                    'price_unit': float(item['price']),
                    'product_uom': ormWebsite.get_default_uom(
                            cursor, user, context
                    ).id,  # context: magento_website ???
                    'product_uom_qty': float(item['qty_ordered']),
                    'magento_notes': item['product_options'],
                    'type': 'make_to_order',
                    'tax_id': [(6, 0, taxes)], #???
                    'product_id':
                        ormProduct.crea8s_find_or_create_using_magento_id(
                            cursor, user, item['product_id'],
                            context=context
                    ).id
                }
                line_data.append((0, 0, values))

            #??? 
            # If the product is a child product of a bundle product, do not
            # create a separate line for this.
            if 'bundle_option' in item['product_options'] and \
                    item['parent_item_id']:
                continue

        # Handle bundle products.
        # Find/Create BoMs for bundle products
        # If no bundle products exist in sale, nothing extra will happen
        #???
        ormMRP_Bom.crea8s_find_or_create_bom_for_magento_bundle(
            cursor, user, data_importing, context
        )

        return line_data
    
    
    #????????
    def crea8s_get_magento_taxes(self, cursor, user, item_data, context):
        """Match the tax in openerp with the tax rate from magento
        Use this tax on sale line

        :param cursor: Database cursor
        :param user: ID of current user
        :param item_data: Item Data from magento
        :param context: Application context
        """
        ormTax = self.pool.get('account.tax')

        # Magento does not return the name of tax
        # First try matching with the percent
        tax_ids = ormTax.search(cursor, user, [
            ('amount', '=', float(item_data['tax_percent']) / 100),
#             ('crea8s_used_on_magento', '=', True) ,
        ], context=context)

        # FIXME This will fail in the case of bundle products as tax comes
        # comes with the children and not with parent

        return tax_ids
    
    #????????
    def crea8s_get_magento_shipping_tax(self, cursor, user, data_importing, context):
        """Match the tax in openerp which has been selected to be applied on
        magento shipping.

        :param cursor: Database cursor
        :param user: ID of current user
        :param data_importing: Order Data from magento
        :param context: Application context
        """
        ormTax = self.pool.get('account.tax')

        # Magento does not return the name of tax or rate
        # We can match only using the field set on tax in openerp itself
        tax_ids = ormTax.search(cursor, user, [
#             ('crea8s_apply_on_magento_shipping', '=', True),
#             ('crea8s_used_on_magento', '=', True),
        ], context=context)

        return tax_ids
    
    
    
#     def process_sale_using_magento_state(
#         self, cursor, user, sale, magento_state, context
#     ):
#         """Process the sale in openerp based on the state of order
#         when its imported from magento
# 
#         :param cursor: Database cursor
#         :param user: ID of current user
#         :param sale: Browse record of sale
#         :param magento_state: State on magento the order was imported in
#         :param context: Application context
#         """
#         # TODO: Improve this method for invoicing and shipping etc
#         orm_magento_order_state = self.pool.get('magento.order_state')
# 
#         state_ids = orm_magento_order_state.search(cursor, user, [
#             ('code', '=', magento_state),
#             ('instance', '=', context['magento_instance'])
#         ])
# 
#         if not state_ids:
#             raise osv.except_osv(
#                 _('Order state not found!'),
#                 _('Order state not found/mapped in OpenERP! '
#                   'Please import order states on instance'
#                  )
#             )
# 
#         state = orm_magento_order_state.browse(
#             cursor, user, state_ids[0], context=context
#         )
#         openerp_state = state.openerp_state
# 
#         # If order is canceled, just cancel it
#         if openerp_state == 'cancel':
#             self.action_cancel(cursor, user, [sale.id], context)
#             return
# 
#         # Order is not canceled, move it to quotation
#         self.action_button_confirm(cursor, user, [sale.id], context)
# 
#         if openerp_state in ['closed', 'complete', 'processing']:
#             self.action_wait(cursor, user, [sale.id], context)
# 
#         if openerp_state in ['closed', 'complete']:
#             self.action_done(cursor, user, [sale.id], context)
    
    
    
    
    
    
    
    
    
